import json


from sqlalchemy.orm import Session
from core.response import resp_500
from core.logger import logger
from app.monitor_metrics.models.prom_alarm_set import PromAlarmSet
from common.welab_k8s.k8s_prometheus import K8sPrometheus


class PromAlarmSetHandler():
    """  PromAlarmRuleSet Handler
    """
    def __init__(self):
        self.k8s_prometheus = K8sPrometheus()
        pass


    def get_alarm_set_search(self, db: Session, page: int, per_page: int, field: str, value: str):
        """
        根据表字段模糊匹配，获取告警规则集信息
        """
        try:
            if per_page:
                field_info = {field: value}
                order_info = {"classes": "asc", "name": "asc"}
                result = PromAlarmSet.filter_by_field_search(db, page, per_page, field_info, order_info)
                if not result:
                    logger.warning(f"get alarm set search, result is null => {field}:{value}")
                    return False, None
            else:
                result = PromAlarmSet.get_entries(db)

        except Exception as e:
            message = f"get alarm set search by {field}:{value} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return True, result

    def get_alarm_set_match(self, db: Session, page: int, per_page: int, field: str, value: str):
        """
        根据表字段完全匹配，获取告警规则集信息
        """
        try:
            result = PromAlarmSet.filter_by_field_match(db, page, per_page, {field: value})
            if not result:
                logger.warning(f"get alarm set match, result is null => {field}:{value}")
                return False

        except Exception as e:
            message = f"get alarm set match by {field}:{value} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return result


    def get_alarm_set_alarm_metrics(self, db: Session, alarm_metrics_uuid: int):
        """
        根据告警指标, 获取告警规则集信息
        """
        try:
            result = PromAlarmSet.get_object_info_by_alarm_metrics(db, alarm_metrics_uuid)
            if not result:
                logger.warning(f"get alarm set alarm_metrics, result is null => {alarm_metrics_uuid}:{alarm_metrics_uuid}")
                return False, None

        except Exception as e:
            message = f"get alarm set alarm_metrics by {alarm_metrics_uuid}:{alarm_metrics_uuid} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return True, result


    def get_alarm_set_group(self, db: Session, uuid: int):
        """
        根据规则集的uuid,获取相关的规则组信息
        """
        try:
            if not PromAlarmSet.get_object_by_uuid(db, uuid):
                logger.error(f"get alarm set group, uuid:{uuid} not exist")
                return False, None
            alarm_set_info = PromAlarmSet.get_object_info_by_uuid(db, uuid)
        except Exception as e:
            message = f"get alarm set group by uuid:{uuid} error"
            logger.exception(f"{message} => {e}")
            return resp_500(message)

        return True, alarm_set_info["alarm_groups"]



    def add_alarm_set(self, db: Session, data: dict):
        """
        创建告警规则集
        """
        try:
            alarm_set_object = PromAlarmSet.get_object_by_name(db, data["name"])
            if alarm_set_object:
                # 如果存在， 则异常返回
                logger.error(f"add alarm set failed,{data['name']} was exist")
                return False

            # k8s集群创建告警规则
            data["alarm_groups"] = []
            prometheus_rule_data = self.k8s_prometheus.convert_rule_data(db, data)
            result = self.k8s_prometheus.create_prometheus_rule(prometheus_rule_data)
            if not result:
                logger.error(f"create prometheus rule failed")
                return False

            # 增加到数据库
            result = PromAlarmSet.add(db, data)
            if not result:
                logger.error(f"add alarm set to database failed")
                return False
        except Exception as e:
            message = f"add alarm group error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True



    def alarm_set_sync_prometheus_rule(self, db: Session, uuid: int):
        # 更新k8s集群告警规则
        alarm_set_info = PromAlarmSet.get_object_info_by_uuid(db, uuid)
        prometheus_rule_data = self.k8s_prometheus.convert_rule_data(db, alarm_set_info)
        result = self.k8s_prometheus.update_prometheus_rule(prometheus_rule_data)
        if not result:
            logger.error(f"alarm set sync prometheus rule failed")
            return False
        return True


    def update_alarm_set(self, db: Session, data: dict):
        """
        更新告警规则集信息
        """
        try:
            alarm_set_object = PromAlarmSet.get_object_by_uuid(db, data["uuid"])
            if not alarm_set_object:
                # 如果不存在， 则异常返回
                logger.error(f"update alarm set failed, uuid:{data['uuid']} not exist")
                return False

            # 更新k8s集群告警规则
            result = self.alarm_set_sync_prometheus_rule(db, data["uuid"])
            if not result:
                logger.error(f"update_alarm_set: update prometheus rule failed")
                return False

            # 更新数据库告警规则集
            result = PromAlarmSet.update(db, data)
            if not result:
                logger.error(f"update alarm set to database failed")
                return False
        except Exception as e:
            message = f"update alarm group error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True



    def sync_alarm_set(self, db: Session, data: dict):
        """
        同步告警规则集信息到prometheus
        """
        try:
            if data["uuid"] != 0:
                # 检查告警规则集是否存在
                alarm_set_object = PromAlarmSet.get_object_by_uuid(db, data["uuid"])
                if not alarm_set_object:
                    # 如果不存在， 则异常返回
                    logger.error(f"sync alarm set failed, uuid:{data['uuid']} not exist")
                    return False
                alarm_sets_uuid = [data["uuid"]]
            else:
                # uuid为0，则任务是同步所有的告警规则
                alarm_set_infos = PromAlarmSet.get_object_infos_by_light(db)
                alarm_sets_uuid = [
                    alarm_set_info["uuid"]
                    for alarm_set_info in alarm_set_infos
                ]

            for alarm_set_uuid in alarm_sets_uuid:
                alarm_set_info = PromAlarmSet.get_object_info_by_uuid(db, alarm_set_uuid)
                k8s_prometheus_rule =self.k8s_prometheus.get_prometheus_rule(alarm_set_info["name"])
                if not k8s_prometheus_rule:
                    # 如果不存在就创建
                    prometheus_rule_data = self.k8s_prometheus.convert_rule_data(db, alarm_set_info)
                    result = self.k8s_prometheus.create_prometheus_rule(prometheus_rule_data)
                    if not result:
                        logger.error(f"create prometheus rule failed")
                        return False
                    logger.info(f"create prometheus rule:{alarm_set_info['name']} success")
                else:
                    # 存在则更新
                    result = self.alarm_set_sync_prometheus_rule(db, alarm_set_uuid)
                    if not result:
                        logger.error(f"update_alarm_set: update prometheus rule failed")
                        return False
                    logger.info(f"update prometheus rule:{alarm_set_info['name']} success")
        except Exception as e:
            message = f"sync alarm set error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        logger.info(f"sync alarm set success")
        return True



    def delete_alarm_set(self, db: Session, data: dict):
        """
        删除告警规则集信息
        """
        try:
            # 检查告警规则集是否存在
            alarm_set_object = PromAlarmSet.get_object_by_uuid(db, data['uuid'])
            if not alarm_set_object:
                logger.error(f"delete alarm set failed, uuid:{data['uuid']} not exist")
                return False

            # 告警规则集内的告警规则是否清空
            alarm_set_info = PromAlarmSet.get_object_info_by_uuid(db, data['uuid'])
            if len(alarm_set_info["alarm_groups"]) != 0:
                logger.error(f"delete alarm set failed, alarm_groups is not empty")
                return False

            # 删除k8s集群的告警规则
            result = self.k8s_prometheus.delete_prometheusrule(alarm_set_info["name"])
            if not result:
                logger.error(f"delete prometheus rule from k8s failed")
                return False

            # 删除数据库中的告警集
            PromAlarmSet.delete_object_by_uuid(db, data['uuid'])
        except Exception as e:
            message = f"delete alarm set error"
            logger.exception(f"{message} data:{data} => {e}")
            return resp_500(message)

        return True


    
    def check_alarm_set(self, db: Session, data: dict):
        # 检查告警规则集是否存在
        alarm_set_object = PromAlarmSet.get_object_by_name(db, data['name'])
        if not alarm_set_object:
            # 不存在，则增加
            result = self.add_alarm_set(db, data)
            if not result:
                logger.error(f"check alarm set failed")
                return False

        # 返回告警规则集的信息
        alarm_set_info = PromAlarmSet.get_object_info_by_name(db, data['name'])
        return alarm_set_info







